/* components */
import { 
  SettingGPTViewHeader,
  SettingGPTViewContent,
  SettingGPTViewContentTitle,
  SettingGPTViewContentSubTitle,
  SettingGPTServiceCardList
} from "@gpt/components"
import CommonModelGroup from "@gpt/views/home/model-group"
import ChannelGroup from "@gpt/views/edit/channel-group"
import SettingGPTEditViewTabs from "@gpt/views/edit/tabs"
import SettingGPTEditViewModulesInside from "@gpt/views/edit/module-inside"
import SettingGPTEditViewModulesOutside from "@gpt/views/edit/module-outside"
import SettingGPTEditViewModulesCommon from "@gpt/views/edit/module-common"
import SettingGPTEditViewModulesPlugin from "@gpt/views/edit/module-plugin"
import SettingGPTEditViewModulesDescription from "@gpt/views/edit/description"
import { DingtalkAssistantDialog, DingtalkAssistantDocTable } from "@gpt/views/edit/dingtalk-assistant"
/* enum */
import ComponentNameEnum from "@model/enum/ComponentNameEnum"
/* hooks */
import { useInitXiaoBaoChat, useSettingGPTRobotEdit, useSettingGPTRobotEditTab, useSettingGPTRobotHome } from "@gpt/hooks"
/* models */
import { 
  SettingGPTChannelEnum,
  SettingGPTRobotChannelList,
  SettingGPTRobotInsideModules, 
  SettingGPTRobotModelModuleEnum, 
  SettingGPTRobotModelModules, 
  SettingGPTRobotPluginModules 
} from "@gpt/model"
/* vue */
import { defineComponent } from "vue"
/* scss */
import "@gpt/views/edit/index.scss"
/* types */
import { SettingGPTRobotChannelType, SettingGPTRobotConfigType, SettingGPTRobotModuleConfigType, SettingGPTServiceItem } from "@gpt/types"
/* util */
import { stringify } from "@src/util/lang/object"
import { isFalsy } from "@src/util/type"
import { isRobotSystem } from "@gpt/utils"
import { getRootWindow } from "pub-bbx-utils"
import { message } from "@src/util/message"
import platform from "@src/platform"
import { openTabGptRobotHome } from "@src/util/business/openTab"
import { getRootWindowInitData } from "@src/util/window"
import Platform from '@src/util/platform';
import { useEnv } from "@hooks/useEnv"
import MsgModel from "@model/MsgModel"

type SettingGPTServiceCardListComponent = InstanceType<typeof SettingGPTServiceCardList>
type DingtalkAssistantDialogComponent = InstanceType<typeof DingtalkAssistantDialog>
type DingtalkAssistantDocTableComponent = InstanceType<typeof DingtalkAssistantDocTable>

export default defineComponent({
  name: ComponentNameEnum.SettingGPTEditView,
  props: {
    
  },
  setup(props, { emit }) {
    
    const { 
      robotId, 
      loading,
      gptRobot, 
      allOutsideModules, 
      gptRobotAppList,
      initialize, 
      fetchGptRobotAppAdd,
      onUpdateRobotSettingHandler, 
      onUpdateRobotSettingModelNameHandler,
      onUpdateRobotSettingReleaseChannelCheckRepeatHandler,
      onDelRobotAppServiceHandler,
      onfetchGptRobotAppListHandler,
      onAddRobotAppServiceHandler,
      onUpdateOpenDDAssistantHandler
    } = useSettingGPTRobotEdit()
    
    const { setActive, active, isPrivateModelActive, isPublicModelActive } = useSettingGPTRobotEditTab()
    const { initChat } = useInitXiaoBaoChat()
    const { isDev } = useEnv()
    
    return {
      isDev,
      robotId,
      loading,
      setActive,
      initialize,
      onUpdateRobotSettingHandler,
      gptRobot,
      allOutsideModules,
      active,
      isPrivateModelActive,
      isPublicModelActive,
      initChat,
      gptRobotAppList,
      onfetchGptRobotAppListHandler,
      onDelRobotAppServiceHandler,
      fetchGptRobotAppAdd,
      onAddRobotAppServiceHandler,
      onUpdateRobotSettingModelNameHandler,
      onUpdateOpenDDAssistantHandler,
      onUpdateRobotSettingReleaseChannelCheckRepeatHandler
    }
  },
  data() {
    return {
      channel: SettingGPTRobotChannelList,
      isIMOpen: false,
      isDocLoading: false
    }
  },
  computed: {
    imAuth(): boolean {
      return this.isIMOpen
    },
    channelList(): SettingGPTRobotChannelType[] {
      return this.channel.filter(item => {
        if (item.value === SettingGPTChannelEnum.IM) {
          return !this.imAuth
        }
        return false
      })
    },
    inOnlyOneAndSystemChannel(): boolean {
      return this.channelList.length === 1 && this.channelList[0].value === SettingGPTChannelEnum.System
    },
    attrs(): Record<string, any> {
      return {
        directives: [
          {
            name: 'loading',
            value: this.loading || this.isDocLoading
          }
        ]
      }
    },
    robotSetting(): SettingGPTRobotConfigType {
      return this.gptRobot.setting
    },
    robotName(): string {
      return this.gptRobot.name || ''
    },
    insideModuleConfig(): SettingGPTRobotModuleConfigType {
      return this.robotSetting.insideModuleConfig
    },
    outsideModuleConfig(): SettingGPTRobotModuleConfigType {
      return this.robotSetting.outsideModuleConfig
    },
    urlModuleConfig(): SettingGPTRobotModuleConfigType {
      return this.robotSetting.urlModuleConfig
    },
    commonModuleConfig(): SettingGPTRobotModuleConfigType {
      return this.robotSetting.commonModuleConfig
    },
    pluginModuleConfig(): SettingGPTRobotModuleConfigType {
      return this.robotSetting.pluginModuleConfig
    },
    modelName(): string {
      
      if (this.isDingtalkAssistant) {
        return SettingGPTRobotModelModuleEnum.Other
      }
      
      return this.gptRobot?.setting?.modelName || ''
    },
    isDingtalkAssistant(): boolean {
      return Boolean(this.gptRobot.setting?.openDDAssistant)
    },
    releaseChannel(): number {
      return this.gptRobot?.releaseChannel || SettingGPTChannelEnum.System
    },
    loginUser(): Record<string, any> {
      const rootWindowInitData = getRootWindowInitData()
      return rootWindowInitData.user || {}
    },
    loginUserAuth(): Record<string, any> {
      return this.loginUser?.auth || {}
    },
    isAllowEdit(): boolean {
      return Boolean(this.loginUserAuth?.XIAOBAO_GPT_EDIT)
    },
    isNotAllowEdit(): boolean {
      return isFalsy(this.isAllowEdit)
    },
    isSystemRobot(): boolean {
      return isRobotSystem(this.gptRobot)
    },
    settingGPTServiceCardListComponent(): SettingGPTServiceCardListComponent {
      return this.$refs.SettingGPTServiceCardList as SettingGPTServiceCardListComponent
    },
    dingtalkAssistantDialogComponent(): DingtalkAssistantDialogComponent {
      return this.$refs.DingtalkAssistantDialog as DingtalkAssistantDialogComponent
    },
    dingtalkAssistantDocTableComponent(): DingtalkAssistantDocTableComponent {
      return this.$refs.DingtalkAssistantDocTable as DingtalkAssistantDocTableComponent
    },
    title(): string {
      return '小宝AI机器人模型设置'
    },
    serviceTitle(): string {
      return 'AI应用服务管理'
    },
    abilityTitle(): string {
      return 'AI能力来源'
    },
    commonModelTitle() {
      return '通用模型'
    },
    commonModelSubTitle() {
      return '通用大模型是指能够处理多个不同任务领域的模型，它能识别自然语言来帮助处理很多问题。'
    },
    channelTitle(): string {
      return 'AI应用场景'
    },
    channelSubTitle(): string {
      return 'AI机器人支持应用于很多渠道/场景，请选择机器人的应用场景。'
    },
    dingtalkTitle(): string {
      return '钉钉AI助理'
    },
    dingtalkSubTitle(): string {
      return '开启后，将与钉钉AI生态能力结合，使体验更便捷。'
    },
    // 是否在钉钉环境
    isDingTalk() {
      return Platform.isDingDingDesktop()
    },
  },
  mounted() {
    this.initialize()
    this.isIMOpen = localStorage.getItem('im_isOpen') == '1'
  },
  methods: {
    onNameChangeHandler(value: string) {
      this.gptRobot.name = value
    },
    onChangeInsideModuleConfigHandler(value: SettingGPTRobotModuleConfigType) {
      this.gptRobot.setting.insideModuleConfig = value
    },
    onChangeOutsideModuleConfigHandler(value: SettingGPTRobotModuleConfigType) {
      this.gptRobot.setting.outsideModuleConfig = value
    },
    onChangeUrlModuleConfigHandler(value: SettingGPTRobotModuleConfigType) {
      this.gptRobot.setting.urlModuleConfig = value
    },
    onChangeCommonModuleConfigHandler(value: SettingGPTRobotModuleConfigType) {
      this.gptRobot.setting.commonModuleConfig = value
    },
    onChangePluginModuleConfigHandler(value: SettingGPTRobotModuleConfigType) {
      this.gptRobot.setting.pluginModuleConfig = value
    },
    onUpdateRobotSettingHandlerImpl() {
      
      const params = {
        id: this.gptRobot.id as unknown as string,
        name: this.gptRobot.name,
        setting: stringify(this.gptRobot.setting) as string
      }
      
      this.onUpdateRobotSettingHandler(params).then(isSuccess => {
        
        if (isFalsy(isSuccess)) {
          return
        }
        
        const isSystem = isRobotSystem(this.gptRobot)
        if (isFalsy(isSystem)) {
          return
        }
        
        this.initChat()
        
      })
      
    },
    async onAddAppHandler(value: string) {
      
      if (isFalsy(value)) {
        message.error('请先选择应用服务能力')
        return
      }
      
      const params = {
        type: value,
        robotId: this.robotId
      }
      
      const isSuccess = await this.fetchGptRobotAppAdd(params)
      if (isFalsy(isSuccess)) {
        return
      }
      
      message.success('添加成功')
      
      this.onfetchGptRobotAppListHandler()
      
      this.settingGPTServiceCardListComponent.closeDialog()
      
      this.initChat()
      
    },
    onDelRobotAppHandlerImpl(value: SettingGPTServiceItem) {
      
      // 非系统机器人且只有一个应用时，不允许删除
      const isNotSystemRobot = isFalsy(this.isSystemRobot)
      const isOnlyOneApp = this.gptRobotAppList.length === 1
      if (isNotSystemRobot && isOnlyOneApp) {
        message.error('至少保留一个应用才能正常使用机器人')
        return
      }
      
      const params = {
        robotId: this.robotId,
        id: value.id as unknown as string
      }
      
      this.onDelRobotAppServiceHandler(params)
      
    },
    onUpdateModelNameHandler(value: string) {      
      this.onUpdateRobotSettingModelNameHandler(value)
    },
    onUpdateReleaseChannelHandler(value: number) {
      this.onUpdateRobotSettingReleaseChannelCheckRepeatHandler(value)
    },
    async onUpdateDingtalkAssistantHandler(value: boolean) {
      try {
        
        // 更新是否开启钉钉AI助理
        const result = await this.onUpdateOpenDDAssistantHandler(value)
        const isSuccess = MsgModel.isSuccess(result)
        if (isSuccess) {
          this.onChangeDingtalkAssistantHandler()
          return
        }

        // 判断是否没有开通钉钉AI助理
        const isNotOpen = result.status == 1001
        if (isNotOpen) {
          this.openDingtalkAssistantDialog()
          console.error('请先开通钉钉AI助理')
          return
        }
        
        // 判断是否没有绑定知识库文档
        const isNotOpenDoc = result.status == 1005
        if (isNotOpenDoc) {
          this.openDingtalkAssistantDocDialog()
          console.error('请先绑定知识库文档')
          return
        }

        message.error(result.message)
        
      } catch (error) {
        console.error('更新是否开启钉钉AI助理失败')
        console.error(error)
      }
    },
    onDingtalkAssistantOpenHandler() {
      const isOpenDingtalkAssistant = true
      this.onUpdateDingtalkAssistantHandler(isOpenDingtalkAssistant)
    },
    onChangeDingtalkAssistantHandler() {
      this.dingtalkAssistantDocTableComponent.initialize()
    },
    openDingtalkAssistantDialog() {
      this.dingtalkAssistantDialogComponent.openDialog()
    },
    openDingtalkAssistantDocDialog() {
      const emptyDocUrl = ''
      this.dingtalkAssistantDialogComponent.openDocDialog(emptyDocUrl)
    },
    editDingtalkAssistantDocDialog() {
      this.dingtalkAssistantDialogComponent.editDocDialog()
    },
    async onDeleteDingtalkAssistantDocHandler() {
      
      const confirmed = await platform.confirm('您确定删除吗？')
      
      if (isFalsy(confirmed)) {
        return
      }
      
      this.dingtalkAssistantDocTableComponent.deleteDingtalkAssistantDoc()
    },
    onBackHandler() {
      
      openTabGptRobotHome()
      
      setTimeout(() => {
        this.closeCurrentTab()
      })
      
    },
    closeCurrentTab() {
      // 关闭当前 tab
      // @ts-ignore
      const id = window.frameElement?.dataset?.id;
      platform.closeTab(id);
    },
    renderSwitch() {
      return (
        <el-switch
          disabled={this.loading || this.isNotAllowEdit}
          value={this.isDingtalkAssistant}
          onChange={this.onUpdateDingtalkAssistantHandler}
        >
        </el-switch>
      )
    },
    renderPrivateTab() {
      
      if (isFalsy(this.isPrivateModelActive)) {
        return
      }
      
      return (
        <div>
          { this.renderModuleInside() }
          { this.renderModuleOutside() }
        </div>
      )
      
    },
    renderModuleInside() {
      return (
        <SettingGPTEditViewModulesInside
          allModules={SettingGPTRobotInsideModules}
          value={this.insideModuleConfig}
          onInput={this.onChangeInsideModuleConfigHandler}
        >
        </SettingGPTEditViewModulesInside>
      )
    },
    renderModuleOutside() {
      return (
        <SettingGPTEditViewModulesOutside
          allModules={this.allOutsideModules}
          value={this.outsideModuleConfig}
          onInput={this.onChangeOutsideModuleConfigHandler}
        >
        </SettingGPTEditViewModulesOutside>
      )
    },
    renderModuleCommon() {
      return (
        <SettingGPTEditViewModulesCommon
          allModules={SettingGPTRobotModelModules}
          value={this.commonModuleConfig}
          onInput={this.onChangeCommonModuleConfigHandler}
        >
        </SettingGPTEditViewModulesCommon>
      )
    },
    renderModulePlugin() {
      return (
        <SettingGPTEditViewModulesPlugin
          allModules={SettingGPTRobotPluginModules}
          value={this.pluginModuleConfig}
          onInput={this.onChangePluginModuleConfigHandler}
        >
        </SettingGPTEditViewModulesPlugin>
      )
    },
    renderPublicTab() {
      
      if (isFalsy(this.isPublicModelActive)) {
        return
      }
      
      return (
        <div>
          { this.renderModuleCommon() }
          { this.renderModulePlugin() }
        </div>
      )
    },
    renderFooter() {
      return (
        <div class="setting-gpt-edit-view__footer">
          <el-button
            type="primary"
            size="medium"
            onClick={this.onUpdateRobotSettingHandlerImpl}
          >
            保存
          </el-button>
        </div>
      )
    },
        /** 
     * @description 渲染 AI 服务能力管理
    */
    renderServiceContent() {
      
      if (this.isDingtalkAssistant) {
        return
      }
      
      return (
        <SettingGPTViewContent
        >
          
          <SettingGPTViewContentTitle
            title={this.serviceTitle}
          >
          </SettingGPTViewContentTitle>
          
          <SettingGPTServiceCardList
            ref="SettingGPTServiceCardList"
            isSystemRobot={this.isSystemRobot}
            disabled={this.isNotAllowEdit}
            robotId={this.robotId}
            value={this.gptRobotAppList}
            onAdd={this.onAddAppHandler}
            onDelete={this.onDelRobotAppHandlerImpl}
          >
          </SettingGPTServiceCardList>
          
        </SettingGPTViewContent>
      )
    },
    /**
     * @description 渲染发布渠道内容
     */
    renderReleaseChannelContent() {
      
      if (this.isSystemRobot) {
        return
      }
      
      // 只有一个渠道且为系统渠道时，不渲染
      if (this.inOnlyOneAndSystemChannel) {
        return
      }
      // 渲染渠道内容
      return (
        <SettingGPTViewContent
        >
          
          <div class="setting-gpt-home-view-channel-content-header">
            
            <div class="setting-gpt-home-view-channel-content-header-title">
              
              <SettingGPTViewContentTitle
                title={this.channelTitle}
              >
              </SettingGPTViewContentTitle>
              
            </div>
            
            <SettingGPTViewContentSubTitle
              title={this.channelSubTitle}
            >
            </SettingGPTViewContentSubTitle>
            
          </div>
          
          <ChannelGroup
            disabled={this.isNotAllowEdit}
            value={this.releaseChannel}
            onInput={this.onUpdateReleaseChannelHandler}
          >
          </ChannelGroup>
          
        </SettingGPTViewContent>
      )
    },
    renderAbilityContentHeader() {
      return (
        <div class="setting-gpt-home-view-ability-content-header">
            
          <div class="setting-gpt-home-view-ability-content-header-title">
            
            <SettingGPTViewContentTitle
              title={this.abilityTitle}
            >
            </SettingGPTViewContentTitle>
            
          </div>
          
        </div>
      )
    },
    /**
     * @description 渲染能力来源内容
     */
    renderAbilityContent() {
      return (
        <SettingGPTViewContent
          class="setting-gpt-home-view-ability-content"
        >
            
          { this.renderAbilityContentHeader() }
          { this.renderDingtalkAssistantContent() }
          { this.renderCommonModelContent() }
          
        </SettingGPTViewContent>
      )
    },
    /** 
     * @description 渲染通用模型
    */
    renderCommonModelContent() {
      return (
        <SettingGPTViewContent
        >
          
          <div class="setting-gpt-home-view-common-model-content-header">
            
            <div class="setting-gpt-home-view-common-model-content-header-title">
              
              <SettingGPTViewContentTitle
                title={this.commonModelTitle}
              >
              </SettingGPTViewContentTitle>
              
              <el-tooltip
                content={this.commonModelSubTitle}
                placement="top"
              >
                <i class="iconfont icon-info"></i>
              </el-tooltip>
              
            </div>
            
            <SettingGPTViewContentSubTitle
              title={this.commonModelSubTitle}
            >
            </SettingGPTViewContentSubTitle>
            
          </div>
          
          <CommonModelGroup
            disabled={this.isNotAllowEdit}
            value={this.modelName}
            isDingtalkAssistant={this.isDingtalkAssistant}
            onInput={this.onUpdateModelNameHandler}
          >
          </CommonModelGroup>
          
        </SettingGPTViewContent>
      )
    },
    /**
     * @description 渲染钉钉AI助手开关
    */
    renderDingtalkAssistantContent() {
      
      // 非钉钉环境时，不渲染
      if (!this.isDingTalk) {
        return
      }
      
      // 非在线客服渠道时，不渲染
      if (this.releaseChannel != SettingGPTChannelEnum.IM) {
        return
      }
      
      return (
        <SettingGPTViewContent>
          
          <div class="setting-gpt-home-view-dingtalk-content-header">
            
            <SettingGPTViewContentTitle
              title={this.dingtalkTitle}
            >
            </SettingGPTViewContentTitle>
            
          </div>
          
          <div class="setting-gpt-home-view-dingtalk-content-switch">
            { this.renderSwitch() }
            <SettingGPTViewContentSubTitle
              title={this.dingtalkSubTitle}
            >
            </SettingGPTViewContentSubTitle>
          </div>
          
          { this.renderDingtalkAssistantDocTable() }
          
        </SettingGPTViewContent>
      )
    },
    renderDingtalkAssistantDocTable() {
      
      if (isFalsy(this.isDingtalkAssistant)) {
        return
      }
      
      return (
        <div class="setting-gpt-home-view-dingtalk-doc-table">
          <div class="setting-gpt-home-view-dingtalk-doc-table-title">
            知识学习来源
          </div>
          <DingtalkAssistantDocTable
            ref="DingtalkAssistantDocTable"
            onAdd={this.openDingtalkAssistantDocDialog}
            onEdit={this.editDingtalkAssistantDocDialog}
            onDelete={this.onDeleteDingtalkAssistantDocHandler}
          >
          </DingtalkAssistantDocTable>
        </div>
      )
    },
    renderDingtalkAssistantSettingButton() {
      
      // 如果没有开启钉钉AI助理，不渲染
      if (!this.isDingtalkAssistant) {
        return
      }
      
      return (
        <div>
          <el-button
            type="text"
            onClick={this.editDingtalkAssistantDocDialog}
          >
            查看配置
          </el-button>
        </div>
      )
    },
    renderHeader() {
      return (
        <div class="setting-gpt-edit-view__header">
          { this.renderBackButton() }
          { this.renderRobotName() }
        </div>
      )
    },
    renderBackButton() {
      return (
        <div 
          class="setting-gpt-edit-view__back-button"
          onClick={this.onBackHandler}
        >
          <i class="iconfont icon-left1"></i>
        </div>
      )
    },
    renderRobotName() {
      return (
        <div class="setting-gpt-edit-view__robot-name">
          { this.robotName }
        </div>
      )
    },
    renderDingtalkAssistantDialog() {
      return (
        <DingtalkAssistantDialog
          ref="DingtalkAssistantDialog"
          onConfirm={this.onDingtalkAssistantOpenHandler}
          onChange={this.onChangeDingtalkAssistantHandler}
        >
        </DingtalkAssistantDialog>
      )
    }
  },
  render() {
    return (
      <div 
        class={ComponentNameEnum.SettingGPTEditView}
        {...this.attrs}
      >
        { this.renderHeader() } 
        { this.renderReleaseChannelContent() }
        { this.renderAbilityContent() }
        { this.renderServiceContent() }
        {this.renderDingtalkAssistantDialog()}

      </div>
    )
  }
})